/**
 * @class Deque
 * https://dev.to/swarup260/data-structures-algorithms-in-javascript-deque-g7b
 * https://dev.to/swarup260/data-structures-algorithms-in-javascript-queue-59al
 * http://code.iamkate.com/javascript/queues/
 * https://www.cnblogs.com/xinkuiwu/p/11586967.html
 */

class Deque {
  constructor() {
    this.items = {}
    this.count = 0
    this.lowestCount = 0
  }

  addFront(element) {
    if (this.isEmpty()) {
      this.addBack(element)
    } else if (this.lowestCount > 0) {
      this.lowestCount--
      this.items[this.lowestCount] = element
    } else {
      for (let index = this.count; index > 0; index--) {
        this.items[index] = this.items[index - 1]
      }
      this.count++
      this.items[0] = element
    }
  }
  addBack(element) {
    this.items[this.count] = element
    this.count++
  }
  removeFront() {
    if (this.isEmpty()) {
      return undefined
    }

    let result = this.items[this.lowestCount]
    delete this.items[this.lowestCount]
    this.lowestCount++
    return result
  }
  removeBack() {
    if (this.isEmpty()) {
      return undefined
    }
    let result = this.items[this.count - 1]
    delete this.items[this.count - 1]
    this.count--
    return result
  }

  peekFront() {
    if (this.isEmpty()) {
      return undefined
    }
    return this.items[this.lowestCount]
  }

  peekBack() {
    if (this.isEmpty()) {
      return undefined
    }
    return this.items[this.count - 1]
  }

  isEmpty() {
    return this.count - this.lowestCount == 0
  }

  size() {
    return this.count - this.lowestCount
  }

  clear() {
    this.items = {}
    this.count = 0
    this.lowestCount = 0
  }

  toString() {
    if (this.isEmpty()) {
      return ''
    }
    let string = `${this.items[this.lowestCount]}`
    for (let index = this.lowestCount + 1; index < this.count; index++) {
      string = `${string},${this.items[index]}`
    }
    return string
  }
}

export default Deque
